package com.sxkiler.demo.common;

import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class AlgorithmDetail {
    static Logger logger = LoggerFactory.getLogger(AlgorithmDetail.class);
    static String workspacePath = "D:/work_git_codes/learning/springdemo/AlgorithmDemo/src/main/java";
    /**
     * @param args
     * @throws Exception
     * data,question,{titleSlug,metaData,content(<strong>Input:</strong><strong>Output:</strong><strong>Explanation:</strong>:),translatedTitle,translatedContent,sampleTestCase(param1,param2...),codeSnippets[java],}
     */
    static String listUrl = "https://leetcode-cn.com/graphql/";
    public static void main(String args[]) throws Exception{
//        System.out.println(FileUtil.readString("ClassTemplate","UTF-8"));
        generateCode("guess-the-word");
    }
    public static String getDeclareClass(String javaCode){
        StringBuffer javaCodeBuf = new StringBuffer();
        String tmpCode = "";
        while(javaCode.indexOf("class")>=0){
            javaCode = javaCode.substring(javaCode.indexOf("class"));
            String nextCode = javaCode.substring(5);
            if(nextCode.indexOf("class")>=0){
                tmpCode = "class "+nextCode.substring(0,nextCode.indexOf("class"));
                tmpCode = tmpCode.substring(0,tmpCode.lastIndexOf("}")+1).replace("*/","").replace("*","").replace("↵","");
                if(!(tmpCode.indexOf("ListNode")>=0 || tmpCode.indexOf("TreeNode")>=0)){
                    javaCodeBuf.append(tmpCode).append("\r\n");
                }
                javaCode = nextCode.substring(nextCode.indexOf("class"));
            }else{
                break;
            }
        }
        return javaCodeBuf.toString();
    }
    public static void generateCode(String titleSlug) throws Exception {
        Map valueMap = new HashMap();
        valueMap.put("titleSlug",titleSlug);
        Map paramMap = new HashMap<>();
        paramMap.put("operationName","questionData");
        paramMap.put("query","query questionData($titleSlug: String!) {\n  question(titleSlug: $titleSlug) {\n    questionId\n    questionFrontendId\n    boundTopicId\n    title\n    titleSlug\n    content\n    translatedTitle\n    translatedContent\n    isPaidOnly\n    difficulty\n    likes\n    dislikes\n    isLiked\n    similarQuestions\n    contributors {\n      username\n      profileUrl\n      avatarUrl\n      __typename\n    }\n    langToValidPlayground\n    topicTags {\n      name\n      slug\n      translatedName\n      __typename\n    }\n    companyTagStats\n    codeSnippets {\n      lang\n      langSlug\n      code\n      __typename\n    }\n    stats\n    hints\n    solution {\n      id\n      canSeeDetail\n      __typename\n    }\n    status\n    sampleTestCase\n    metaData\n    judgerAvailable\n    judgeType\n    mysqlSchemas\n    enableRunCode\n    envInfo\n    book {\n      id\n      bookName\n      pressName\n      source\n      shortDescription\n      fullDescription\n      bookImgUrl\n      pressImgUrl\n      productUrl\n      __typename\n    }\n    isSubscribed\n    isDailyQuestion\n    dailyRecordStatus\n    editorType\n    ugcQuestionId\n    style\n    __typename\n  }\n}\n");
        paramMap.put("variables",valueMap);
        HttpRequest request = HttpUtil.createPost(listUrl);
        Map header = new HashMap();
        header.put("x-csrftoken","KuwJ0GJtHqM39FgX45y5tRUdOSVq1DNwIpBQcRhdAdQD3YvoAcw2etf96h0N9AB0");
        header.put("x-definition-name","question");
        header.put("x-operation-name","questionData");
        header.put("content-type","application/json");
        header.put("sec-fetch-mode","cors");
        header.put("sec-fetch-site","same-origin");
        header.put("user-agent","Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36");
        header.put("cookie","csrftoken=KuwJ0GJtHqM39FgX45y5tRUdOSVq1DNwIpBQcRhdAdQD3YvoAcw2etf96h0N9AB0;");
        String requestPayload = JSON.toJSONString(paramMap);
        String resultJson = request.addHeaders(header).body(requestPayload).execute().body();
        try{
            //解析返回数据
            Map result = JSON.parseObject(resultJson);
            Map data = (Map)result.get("data");
            Map templateMap = getTemplateMap((Map)data.get("question"));
            if(templateMap==null){
                logger.info("题目内容不全,{}",titleSlug);
                return;
            }
            String classContent = getClassContent(templateMap, "ClassTemplate");
            //处理name的内容
            String name = (String)templateMap.get("__questionName__");

            //
            String filePath = workspacePath+"/com/sxkiler/demo/"+templateMap.get("__level__")+"/"+name+".java";
            FileUtil.writeBytes(classContent.getBytes("utf-8"),filePath);
        }catch (Exception ex){
            logger.info("requestInfo={}",requestPayload);
            logger.info("responseInfo={}",resultJson);
            logger.error("执行异常,{},{}",titleSlug,ex.getMessage(),ex);
            throw ex;
        }

    }
    private static String getClassContent(Map templateMap,String templatePath){
        String template = FileUtil.readString(templatePath,"utf-8");
        Iterator<Map.Entry<String,String>> it = templateMap.entrySet().iterator();
        while(it.hasNext()){
            Map.Entry<String,String> entry = it.next();
            template = template.replaceAll(entry.getKey(),entry.getValue());
        }
        return template;
    }
    private static String getJavaType(String type){
        return type.replaceAll("integer","Integer")
                .replaceAll("string","String")
                .replaceAll("character","String")
                .replaceAll("list","List")
                .replaceAll("double","Double")
                .replaceAll("float","Float")
                .replaceAll("boolean","Boolean")
                .replaceAll("vector","Vector")
                .replaceAll("map","Map");
    }
    private static Map getTemplateMap(Map question){
        if(question.get("translatedContent")==null && question.get("content") == null)return null;
        Map templateMap = new HashMap();
        String metaData = (String)question.get("metaData");
        List<Map> codeList = (List)question.get("codeSnippets");
        String javaCode = "";
        if(codeList!=null){
            for(Map map:codeList){
                if("java".equalsIgnoreCase((String)map.get("lang"))){
                    javaCode = (String)map.get("code");
                    break;
                }
            }
        }
        ///**↵ * Definition for singly-linked list.↵ * public class ListNode {↵ *     int val;↵ *     ListNode next;↵ *     ListNode() {}↵ *     ListNode(int val) { this.val = val; }↵ *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }↵ * }↵ */↵class Solution {↵    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {↵        ↵    }↵}
        Map meta = JSON.parseObject(metaData);
        List<Map> paramsList = (List)meta.get("params");
        StringBuffer paramBuf = new StringBuffer();
        if(paramsList!=null){
            for(int i=0;i<paramsList.size();i++){
                if(i>0)paramBuf.append(",");
                Map param = paramsList.get(i);
                String type = getJavaType((String)param.get("type"));
                paramBuf.append(type).append(" ").append("param"+i);

            }
        }
        Map returnMap = (Map)meta.get("return");
        String returnType = getJavaType((String)returnMap.get("type"));
        Object value = null;
        if(",Double,Integer,Float,Long".indexOf(returnType)>0){
            value = "return 0;";
        }else if("Boolean".equalsIgnoreCase(returnType)){
            value = "return false;";
        }else if("void".equalsIgnoreCase(returnType)){
            value = "return;";
        }else{
            value = "return null;";
        }
        //名字处理
        String titleSlug = (String)question.get("titleSlug");
        String name = (String)meta.get("name");
        if(name==null) name = titleSlug;
        name = name.trim().replace("-","_");
        //内容
        String content = question.get("translatedContent") == null?(String)question.get("content"):(String)question.get("translatedContent");
        content = java.util.regex.Matcher.quoteReplacement(content.replace("↵","\n").replaceAll("/\\*","").replaceAll("\\*/",""));
        //标题处理
        String title = titleSlug+"="+question.get("translatedTitle");
        String level = question.get("difficulty").toString().toLowerCase();
        templateMap.put("__level__",level);
        templateMap.put("__translatedTitle__",title);
        templateMap.put("__translatedContent__",content);
        templateMap.put("__sampleTestCase__",(String)question.get("sampleTestCase"));
        templateMap.put("__questionName__",name);
        templateMap.put("__returnType__",returnType);
        templateMap.put("__returnValue__",String.valueOf(value));
        templateMap.put("__questionClass__",getDeclareClass(javaCode));
        templateMap.put("__questionParams__",paramBuf.toString());
        return templateMap;
    }
}
